#include <iostream>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "platdep.h"
#ifndef BASE_TYPE_H_
#define BASE_TYPE_H_

const int OP_NULL = 0x0; // None
const int OP_EQUALITY = 0x01; // ==, !=
const int OP_RELATIONAL = 0x02; // <, >,<=, >=
const int OP_MATHEMATICAL = 0x04; // +, -, *, /, %
const int OP_BITWISE = 0x08; // ~, ^, &, |

using namespace std;


class BaseType {
public:
	virtual N32 getOperations(){ return OP_NULL; }
	virtual N32 checkValue(char *operand, char *table_name = NULL) = 0; //Check if operand is of a compatible type
	virtual N32 getMaxValue() = 0;
	virtual N32 getMinValue() = 0;
	virtual N32 getType() = 0;
protected:
private:
};


class IntType:public BaseType {
public:
	virtual N32 getOperations() { return OP_EQUALITY|OP_RELATIONAL|OP_MATHEMATICAL|OP_BITWISE; }
	virtual N32 checkValue(char *operand, char *table_name = NULL) {return 0;}
	virtual N32 getMaxValue(){ return INT_MAX ;}
	virtual N32 getMinValue() {return INT_MIN;} 
	virtual N32 getType() { return 0;}
	
private:
		
};

class N32Type: public IntType {
public:
	N32Type &operator=(N32 val) { mVal = val; return *this; }
	N32Type &operator=(N32Type &val) { mVal = val.mVal; return *this; }
	N32Type &operator=(char *val) { mVal = int(val); return *this; }
	
	bool operator==(N32 val){ return mVal == val; }
	bool operator==(N32Type &val){ return mVal == val.mVal; }
	bool operator!=(N32 val) { return !(*this == val); }
	//bool operator!=(N32Type &val){ return !(*this == val); }
	
	friend std::ostream& operator<<(std::ostream&, const N32Type&);
	virtual N32 getType() { return 1; }
private:
	int mVal;
};

//inline std::ostream& operator<<(std::ostream &os, const N32Type &val){ os<<mVal; return os; }

class TimestampType:public IntType {
public:
	virtual N32 getOperations() { return OP_EQUALITY|OP_RELATIONAL|OP_MATHEMATICAL;}
	virtual N32 getMaxValue() { return 4000000; }
	virtual N32 getMinValue() { return 0; }
	virtual N32 checkValue(char *operand, char *table_name = NULL);
	virtual N32 getType() { return 2; }
private:
	N32 timestamp;
};

class PortnumType:public IntType {
public:
	virtual N32 getOperations() { return OP_EQUALITY|OP_RELATIONAL|OP_MATHEMATICAL;}
	virtual N32 getMaxValue() { return 4000; }
	virtual N32 getMinValue() { return 0; }
	virtual N32 checkValue(char *operand, char *table_name = NULL);
	virtual N32 getType() { return 3; }
private:
	int portnum;
};


class PacketType:public IntType {
public:
	virtual N32 getOperations() { return OP_EQUALITY|OP_RELATIONAL|OP_MATHEMATICAL;}
	virtual N32 getMaxValue() { return 100000; }
	virtual N32 getMinValue() { return 0; }
	virtual N32 checkValue(char *operand, char *table_name = NULL);
	virtual N32 getType() { return 4; }
private:
	N32 packet;
};


class ByteType:public IntType {
public:
	virtual N32 getOperations() { return OP_EQUALITY|OP_RELATIONAL|OP_MATHEMATICAL;}
	virtual N32 getMaxValue() { return 100000; }
	virtual N32 getMinValue() { return 0; }
	virtual N32 checkValue(char *operand, char *table_name = NULL);
	virtual N32 getType() { return 5;}
private:
	N32 byte;
};



class IPv4Type:public BaseType {
public:
	virtual N32 getOperations() { return OP_EQUALITY; }
	virtual N32 checkValue(char *operand, char *table_name = NULL);
	virtual N32 getMaxValue() { return 0; }
	virtual N32 getMinValue() { return 0; }
	virtual N32 getType() { return 6; }
	

	IPv4Type &operator=(N32 val) { mMask = makeMask(0); mIP = val>>mMask; return *this; }
	IPv4Type &operator=(N32 *val) { mMask = makeMask(val[1]); mIP = val[0]>>mMask; return *this; }
	IPv4Type &operator=(IPv4Type &val) { mIP = val.mIP; mMask = val.mMask; return *this; }
	IPv4Type &operator=(char *ip);
	
	bool operator==(N32 ip) { return (mIP == ip>>mMask); }
	bool operator==(IPv4Type &ip) { return ((mIP==ip.mIP)&&(mMask==ip.mMask)); }
	bool operator!=(N32 ip) { return !(*this==ip); }
	bool operator!=(IPv4Type &ip) { return !(*this==ip);}
private:
	N32 makeMask(int mask);
	N32 mIP;
	N32 mMask;
};


class IPv6Type:public BaseType {
public:
	virtual N32 getOperations() { return OP_EQUALITY; }
	virtual N32 checkValue(char *operand, char *table_name = NULL);
	virtual N32 getMaxValue() { return 0; }
	virtual N32 getMinValue() { return 0; }	
	virtual N32 getType() { return 7; }
private:
};


class MACType:public BaseType {
public:
	virtual N32 getOperations() { return OP_EQUALITY; }
	virtual N32 checkValue(char *operand, char *table_name = NULL);
	virtual N32 getMaxValue() { return 0; }
	virtual N32 getMinValue() { return 0; }
	virtual N32 getType() { return 8; }
private:
	
	 
};


class AppType:public BaseType {
public:
	virtual N32 getOperations() { return OP_EQUALITY|OP_RELATIONAL; }
	virtual N32 getMaxValue() { return 500; }
	virtual N32 getMinValue() { return 0; }
	virtual N32 checkValue(char *operand, char *table_name = NULL); //{return 0;}
	virtual N32 getType() { return 9; }

private:
	static const char* content[]; 
};



class FillerType:public BaseType {
public:
	virtual N32 getOperations() { return OP_EQUALITY; }
	virtual N32 checkValue(char *operand, char *table_name = NULL); //{return 0;}
	virtual N32 getMaxValue() { return 0; }
	virtual N32 getMinValue() { return 0; }
	virtual N32 getType() { return 10; }	
private:
	char *filler;
};




#endif
